/*
 * camera_tsk.c
 *
 *  Created on: 2011/06/17
 *      Author: AKS
 */

#include "core/include/aks_processor.h"
#include "core/include/process.h"
#include "core/include/types.h"

#include "core/include/aks_string.h"

#include "app/frame_buffer/include/camera_tsk.h"
#include "app/frame_buffer/include/frame_buffer.h"
#include "app/frame_buffer/include/display_tsk.h"
#include "app/tinySystem/include/tinySystem.h"

#include "app/frame_buffer/chip/include/MT9V032.h"
#include "app/frame_buffer/chip/include/TCM8230.h"

#include "app/cv/include/aksImage.h"
#include "app/cv/include/aksDraw.h"

#include "app/memory/include/memory.h"

DWORD cam_base_adr;
static BYTE  current_buffer_index;
BOOL camera_image_ready_flag;

PROCESS camera_process =
{
	camera_tsk,
    NULL,
    camera_tsk_wakeup,
    NULL,
    0
};

LIST_ITEM cameraItm
=
{
    NULL,
    &camera_process
};

// for using safe.
BOOL camera_image_was_displayed;
BOOL camera_tsk_wakeup_displayed(void *param);

void camera_tsk(void *param)
{
	// New image was ready for display
	if(camera_image_ready_flag == TRUE)
	{
		camera_image_was_displayed = FALSE;

		sleepCurrentProcess(camera_tsk_wakeup_displayed, NULL);
	}
	else
	{
		// switch frame buffer
		current_buffer_index = 0x01 & (current_buffer_index ^ 0x01);
		frame_buffer_switched(cam_base_adr, current_buffer_index);

		sleepCurrentProcess(camera_tsk_wakeup, NULL);
	}

	return;
}

BOOL camera_tsk_wakeup(void *param)
{
    if(frame_buffer_switched(cam_base_adr, current_buffer_index) && FALSE == camera_image_ready_flag)
    {
    	camera_image_ready_flag = TRUE;
        return TRUE;
    }
    else
    {
    	return FALSE;
    }
}

BOOL camera_tsk_wakeup_displayed(void *param)
{
    if(camera_image_was_displayed == TRUE)
    {
        return TRUE;
    }
    else
    {
    	return FALSE;
    }
}

BOOL init_camera_tsk(BYTE SS_index)
{
    /* initialize camera module */
	BYTE tcm8230_Adr = 0x3C;
	BYTE tcm8230_initTable[][2] =
	{
		{0x1E, 0x08},
//		{0x02, 0x00},
//		{0x05, 0x82}, // shutter sppeed ?
//		{0x06, 0x0D}, // shutter sppeed ?
//		{0x1A, 0x00},
		{0x03, DOUT_ON | DOUT_OUT | SIZE_QVGA | FORMAT_RGB565 | COLER_COLOR},
	};

//	for( BYTE i=0 ; i < sizeof(tcm8230_initTable) ; ++i)
	for( BYTE i=0 ; i < 2 ; ++i)
	{
		I2C_transmitBytes(tcm8230_Adr, tcm8230_initTable[i], 2);
	}

	UART_transmitString(UART_DBG, (BYTE *)"TCM8230 is initialized. \r\n");

    /* initialize camera module */
/*
	BYTE mt9v032_initTable[][3] =
	{
		{MT9V032_WINDOW_HEIGHT   , 0x00, 0xF0},
		{MT9V032_WINDOW_WIDTH    , 0x01, 0x40}
	    {MT9V032_TEST_PATTERN    , 0x38, 0x00}
	};

	for( BYTE i=0 ; i < sizeof(mt9v032_initTable) ; ++i)
	{
		I2C_transmitBytes(SLV_ADR_MT9V032, mt9v032_initTable[i], 3);
	}

	UART_transmitString(UART_DBG, (BYTE *)"MT9V032 is initialized. \r\n");
*/

	/* initialize frame buffer */
	cam_base_adr = ((DWORD)(SS_index) << 21) & 0xE00000;
	current_buffer_index = 0;

	init_frame_buffer(cam_base_adr);
    while(!frame_buffer_switched(cam_base_adr, current_buffer_index));

    UART_transmitString(UART_DBG, (BYTE *)"Frame Buffer for CAMERA is initialized. \r\n");

	/* initialize internal logic */
	camera_image_ready_flag = FALSE;
	camera_image_was_displayed = FALSE;

	return TRUE;
}

BOOL isInTargetRange(AksPixel px)
{
	if(px.R > 150 && px.B < 120 && px.G < 120)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

BYTE imgLine[2][320*3];
volatile BOOL lineValid;
void lineTransferd(BOOL status)
{
	lineValid = TRUE;
}

BOOL camera_drawToImage(AksImage *dst, AksPoint offset)
{
	DWORD height = 240;
	DWORD width  = 320;

    if(camera_image_ready_flag != TRUE)
    {
        return FALSE;
    }

    DWORD img_base_adr = cam_base_adr + 0x100000*current_buffer_index;

    DWORD heightSum = 0;
    DWORD widthSum  = 0;
    DWORD tgtCnt    = 0;

	// draw image from camera to LCD
	lineValid = FALSE;
	Memory_startDMA(img_base_adr + (0*width*2), (DWORD)(imgLine[0]), width*2, lineTransferd);
	while(!lineValid);

	WORD wIdx = 320-1;

    for(DWORD j=1 ; j < height ; j++)
	{
		lineValid = FALSE;
		Memory_startDMA(img_base_adr + (j*width*2), (DWORD)(imgLine[j&1]), width*2, lineTransferd);

		while( (lineValid==FALSE) || (wIdx != 0xFFFF) ){
            AksPixel px;
			if(wIdx != 0xFFFF){
				px.R = (imgLine[~j&1][wIdx*2+1] & 0xF8);
				px.G = (imgLine[~j&1][wIdx*2+1] << 5) | (imgLine[~j&1][wIdx*2+0] >>3);
				px.B = (imgLine[~j&1][wIdx*2+0] << 3);
            
				imgLine[~j&1][wIdx*3+0] = px.R;
				imgLine[~j&1][wIdx*3+1] = px.G;
				imgLine[~j&1][wIdx*3+2] = px.B;
			
				--wIdx;
			}			
		}

		lineValid = FALSE;
		wIdx = 320-1;
		Memory_startDMA( (DWORD)imgLine[~j&1], (DWORD)(dst->imgPtr + 3*(j+offset.y)*dst->width) ,  width*3, lineTransferd);
		while(lineValid==FALSE){
            AksPixel px;
			if(wIdx != 0xFFFF){
				px.R = (imgLine[j&1][wIdx*2+1] & 0xF8);
				px.G = (imgLine[j&1][wIdx*2+1] << 5) | (imgLine[j&1][wIdx*2+0] >>3);
				px.B = (imgLine[j&1][wIdx*2+0] << 3);
            
				imgLine[j&1][wIdx*3+0] = px.R;
				imgLine[j&1][wIdx*3+1] = px.G;
				imgLine[j&1][wIdx*3+2] = px.B;
            
				--wIdx;
			}				
		}
	}

    camera_image_ready_flag = FALSE;
    camera_image_was_displayed = TRUE;

    return TRUE;
}


